1 package edu.jiangxin.apktoolbox.swing.extend.filepanel;
2
3 import edu.jiangxin.apktoolbox.utils.Constants;
4 import edu.jiangxin.apktoolbox.utils.FileUtils;
5 import org.apache.commons.lang3.ArrayUtils;
6 import org.apache.commons.lang3.StringUtils;
7 import org.apache.logging.log4j.LogManager;
8 import org.apache.logging.log4j.Logger;
9
10 import javax.swing.*;
11 import javax.swing.filechooser.FileNameExtensionFilter;
12 import java.awt.*;
13 import java.awt.datatransfer.DataFlavor;
14 import java.awt.datatransfer.Transferable;
15 import java.awt.datatransfer.UnsupportedFlavorException;
16 import java.awt.event.ActionEvent;
17 import java.awt.event.ActionListener;
18 import java.io.File;
19 import java.io.IOException;
20 import java.io.Serial;
21 import java.util.List;
22
23 public class FilePanel extends JPanel {
24 @Serial
25 private static final long serialVersionUID = 1L;
26
27 private static final Logger LOGGER = LogManager.getLogger(FilePanel.class.getSimpleName());
28 private JTextField fileTextField;
29
30 private String buttonText;
31
32 private String currentDirectoryPath = ".";
33
34 private int fileSelectionMode = JFileChooser.FILES_ONLY;
35
36 private String description;
37
38 private String[] extensions;
39
40 private JFileChooser fileChooser;
41
42 private transient IFileReadyCallback callback;
43
44 public FilePanel(String buttonText) {
45 super();
46 fileChooser = new JFileChooser();
47 this.buttonText = buttonText;
48 }
49
50
51 public void initialize() {
52 initUI();
53 }
54
55 public void setCurrentDirectoryPath(String currentDirectoryPath) {
56 this.currentDirectoryPath = currentDirectoryPath;
57 }
58
59 public void setPersistentKey(String persistentKey) {
60 fileTextField.setName(persistentKey);
61 }
62
63 public void setFileReadyCallback(IFileReadyCallback callback) {
64 this.callback = callback;
65 }
66
67 public void setFileSelectionMode(int fileSelectionMode) {
68 this.fileSelectionMode = fileSelectionMode;
69 }
70
71 public void setDescriptionAndFileExtensions(String description, String[] extensions) {
72 this.description = description;
73 this.extensions = extensions;
74 if (StringUtils.isNotEmpty(description) || ArrayUtils.isNotEmpty(extensions)) {
75 FileNameExtensionFilter filter = new FileNameExtensionFilter(description, extensions);
76 if (fileChooser != null) {
77 fileChooser.resetChoosableFileFilters();
78 fileChooser.addChoosableFileFilter(filter);
79 fileChooser.setAcceptAllFileFilterUsed(false);
80 }
81 } else {
82 if (fileChooser != null) {
83 fileChooser.resetChoosableFileFilters();
84 fileChooser.setAcceptAllFileFilterUsed(true);
85 }
86 }
87 }
88
89 private void initUI() {
90 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
91
92 fileTextField = new JTextField();
93 fileTextField.setPreferredSize(new Dimension(600, 30));
94 fileTextField.setMaximumSize(new Dimension(1200, 30));
95 fileTextField.setTransferHandler(new FileTransferHandler());
96
97 JButton chooseButton = new JButton(buttonText);
98 chooseButton.addActionListener(new OpenDictionaryFileActionListener());
99
100 add(fileTextField);
101 add(Box.createHorizontalStrut(Constants.DEFAULT_X_BORDER));
102 add(chooseButton);
103 }
104
105 public File getFile() {
106 return new File(fileTextField.getText());
107 }
108
109 class OpenDictionaryFileActionListener implements ActionListener {
110 @Override
111 public void actionPerformed(ActionEvent e) {
112 fileChooser.setCurrentDirectory(new File(currentDirectoryPath));
113 fileChooser.setFileSelectionMode(fileSelectionMode);
114 fileChooser.setMultiSelectionEnabled(false);
115 if (StringUtils.isNotEmpty(description) || ArrayUtils.isNotEmpty(extensions)) {
116 FileNameExtensionFilter filter = new FileNameExtensionFilter(description, extensions);
117 fileChooser.addChoosableFileFilter(filter);
118 fileChooser.setAcceptAllFileFilterUsed(false);
119 } else {
120 fileChooser.resetChoosableFileFilters();
121 fileChooser.setAcceptAllFileFilterUsed(true);
122 }
123 int returnVal = fileChooser.showOpenDialog(FilePanel.this);
124 if (returnVal == JFileChooser.APPROVE_OPTION) {
125 File selectedFile = fileChooser.getSelectedFile();
126 fileTextField.setText(FileUtils.getCanonicalPathQuiet(selectedFile));
127 if (callback != null) {
128 callback.onFileReady(selectedFile);
129 }
130 }
131 }
132 }
133
134 class FileTransferHandler extends TransferHandler {
135 @Serial
136 private static final long serialVersionUID = 1L;
137
138 public FileTransferHandler() {
139 }
140
141 @Override
142 public boolean importData(JComponent comp, Transferable t) {
143 List<File> files = null;
144 try {
145 @SuppressWarnings("unchecked")
146 List<File> tmp = (List<File>) t.getTransferData(DataFlavor.javaFileListFlavor);
147 files = tmp;
148 } catch (IOException e) {
149 LOGGER.error("importData failed: IOException");
150 } catch (UnsupportedFlavorException e) {
151 LOGGER.error("importData failed: UnsupportedFlavorException");
152 }
153 if (files == null || files.size() != 1) {
154 LOGGER.error("importData failed: getTransferData failed");
155 return false;
156 }
157 File file = files.get(0);
158 if ((!file.isFile() && fileSelectionMode == JFileChooser.FILES_ONLY)
159 ||(!file.isDirectory() && fileSelectionMode == JFileChooser.DIRECTORIES_ONLY)) {
160 LOGGER.error("importData failed: fileSelectionMode is not match");
161 return false;
162 }
163 fileTextField.setText(FileUtils.getCanonicalPathQuiet(file));
164 if (callback != null) {
165 callback.onFileReady(file);
166 }
167 return true;
168 }
169
170 @Override
171 public boolean canImport(JComponent jComponent, DataFlavor[] dataFlavors) {
172 for (DataFlavor dataFlavor : dataFlavors) {
173 if (DataFlavor.javaFileListFlavor.equals(dataFlavor)) {
174 return true;
175 }
176 }
177 return false;
178 }
179 }
180 }